<script setup lang="ts">
import Empty from '@/components/Empty.vue';
import { CustomRoutePose, getRegionCustomRoutePose, getTaskPose, getWarningByTaskId, RouteAttitude, RoutePoint, TaskItem } from '@/services/task';
import { ElButton, ElMessage, ElScrollbar } from 'element-plus';
import { toLonLatString } from 'common/src/utils/lnglat';
import TaskInfo from './TaskInfo.vue';
import { useTaskStore, judgeItemStatus, useTimeRangeStore, useWeatherStore,useUserStore } from '@/store';
import { Edit, Aim, Hide, View } from '@element-plus/icons-vue';
import ClearSvgUrl from '@/assets/clear.svg?url';
import { getEmptyGeoJson, getWarningMarker, hideRegionRoute, shipRouteLayerId, updateRegionRouteSrc, updateTaskRegionSrc } from 'common/src/utils/layer';
import { convert2DirectedPath } from 'common/src/utils/routeCalc';
import { bbox } from '@turf/turf';
import { GeoJSONFeature, MapMouseEvent, Marker } from 'mapbox-gl';
import { TaskType } from 'common/src/utils/special';
import { getCustomLocalTimeFormat } from 'common/src/utils/time';
import ExportDialog from './ExportDialog.vue';

interface Props {
  visible: boolean;
}

interface Emits {
  (e: "update:visible", visible: boolean): void;
  (e: 'edit', task: TaskItem): void;
}

interface WarningMarker {
  id: number;
  marker: Marker;
  lon: number;
  lat: number;
  records: string;
}

const props = withDefaults(defineProps<Props>(), {
});
const emits = defineEmits<Emits>();
const weatherStore = useWeatherStore();
const taskInfoShow = ref(false);
const chosenTask = ref<TaskItem>();
const taskStore = useTaskStore();
const userStore = useUserStore();
const timeRangeStore = useTimeRangeStore();
const taskInfoRef = ref<InstanceType<typeof TaskInfo> | null>(null);
const attitudeLoading = ref(false);
const customRouteLoading = ref(false);
const chosenTaskAttitude = ref<Record<number, RouteAttitude[]>>({});
const chosenTaskCustomRoute = ref<CustomRoutePose[]>([]);
let mapListenerAdded = false;
const scrollbarRef = ref<InstanceType<typeof ElScrollbar> | null>(null);
const clickActiveTaskId = ref(-1);
const warningMarkers = ref<WarningMarker[]>([]);
const exportDialogRef = ref<InstanceType<typeof ExportDialog> | null>(null);

const show = computed({
  get() {
    return props.visible;
  },
  set(visible: boolean) {
    emits("update:visible", visible);
  },
});

const mapFitTaskBounds = (task: TaskItem) => {
  const geojson = getEmptyGeoJson();
  let hasRoutes = false;
  task.routeType.forEach(type => {
    if (task.routes[type]?.length) {
      hasRoutes = true;
      geojson.features.push({
        type: 'Feature',
        properties: {},
        geometry: {
          type: 'LineString',
          coordinates: convert2DirectedPath(task.routes[type].map((point) => [point.lon, point.lat]))
        }
      });
    }
  });
  if (!hasRoutes) {
    ElMessage({
      type: 'warning',
      message: '该任务暂无已生成航线',
    });
  }
  const [minLng, minLat, maxLng, maxLat] = bbox(geojson);
  const lngRange = (maxLng - minLng) > 100 ? 20 : (maxLng - minLng) * 0.2;
  const latRange = (maxLat - minLat) > 100 ? 20 : (maxLat - minLat) * 0.2;
  weatherStore.map?.fitBounds([
    [minLng - lngRange, minLat - latRange],
    [maxLng + lngRange, maxLat + latRange],
  ]);
}

const getFirstAndLastTime = (points: RoutePoint[], startTime: number, endTime: number) => {
  const firstPoint = points[0];
  const lastPoint = points[points.length - 1];
  let start = firstPoint.ts * 1000;
  let end = lastPoint.ts * 1000;
  if (start > startTime) {
    start = startTime;
  }
  if (end < endTime) {
    end = endTime;
  }
  return [start, end]
};

const getTaskAttitude = async (id: number) => {
  attitudeLoading.value = true;
  try {
    const res = await getTaskPose(id);
    chosenTaskAttitude.value = res.poses || {};
  } catch (err) {
    console.log(err);
    chosenTaskAttitude.value = {};
  } finally {
    attitudeLoading.value = false;
  }
};

const getTaskCustomRoute = async (id: number) => {
  customRouteLoading.value = true;
  try {
    const res = await getRegionCustomRoutePose(id);
    chosenTaskCustomRoute.value = res;
    const lineGeoJson = getEmptyGeoJson();
    const pointGeoJson = getEmptyGeoJson();
    res.forEach((route, idx) => {
      lineGeoJson.features.push({
        type: 'Feature',
        properties: {
          id, idx,
        },
        geometry: {
          type: 'LineString',
          coordinates: convert2DirectedPath((route.points || []).map((point) => {
            return [point.lon, point.lat];
          })),
        },
      });
      route.points.forEach((point) => {
        pointGeoJson.features.push({
          type: 'Feature',
          properties: {
            id, idx,
            ...point,
          },
          geometry: {
            type: 'Point',
            coordinates: [point.lon, point.lat],
          }
        });
      });
    });
    updateRegionRouteSrc(weatherStore.map as any, lineGeoJson, pointGeoJson);
  } catch (err) {
    console.log(err);
    chosenTaskCustomRoute.value = [];
  } finally {
    customRouteLoading.value = false;
  }
};

const getTaskWarnings = async (id: number) => {
  warningMarkers.value.forEach(item => {
    item.marker.remove();
  });
  warningMarkers.value = [];
  let markerId = 0;
  try {
    const res = await getWarningByTaskId(id);
    const lineColorObj = {
      id,
      alertWaveHeight: res.alertWaveHeight,
      alertWindSpeed: res.alertWindSpeed,
      routes: (() => {
        const rts: Record<number, { lon: number; lat: number; windSpeed: number; waveHeight: number }[]> = {};
        Object.entries(res.routes || {}).forEach(([type, routesArr]) => {
          const t = Number(type);
          const pts = routesArr.map(route => ({
            lon: route.lon,
            lat: route.lat,
            windSpeed: route.wind?.knots,
            waveHeight: route.wave?.seaWaveHeight
          }));
          rts[t] = pts;
        });
        return rts;
      })(),
    }
    const iconObj = {
      id,
      routes: (() => {
        const rts: Record<number, { lon: number; lat: number; windDegree: number; windKnots: number; seaWaveDegree: number }[]> = {};
        Object.entries(res.routes || {}).forEach(([type, routesArr]) => {
          const t = Number(type);
          const pts = routesArr.map(route => ({
            lon: route.lon,
            lat: route.lat,
            windDegree: route.wind?.degree,
            windKnots: route.wind?.knots,
            seaWaveDegree: route.wave?.seaWaveDegree
          }));
          rts[t] = pts;
        });
        return rts;
      })(),
    }
    // Store active task stage and line color object
    taskStore.setActiveTaskStage(res.taskStage ?? null);
    taskStore.setActiveLineColorObj(lineColorObj);

    /** 战备航渡的航线加上浪方向和风羽图（使用 store 中的激活阶段） */
    if (taskStore.activeTaskStage === 3) {
      taskStore.addRouteWindWaveMarkers(iconObj);
    }
    // 如果已经返回列表了，那就不需要添加了
    if (!taskInfoShow.value) {
      return;
    }
    /** 危险报文警告⚠️标记 */
    Object.entries(res.routes || {}).forEach(([_type, points]) => {
      points.forEach((point) => {
        if (point.warnInfo?.abj?.length || point.warnInfo?.wave?.length || point.warnInfo?.wind?.length) {
          const { lat, lon, ts } = point;
          const warningId = markerId;
          markerId += 1;
          const time = getCustomLocalTimeFormat(ts * 1000, 'YYYY-MM-DD HH:mm:ss');
          const lngLat = toLonLatString(lon, lat);
          let msgs: string[] = [];
          if (point.warnInfo?.wave?.length) {
            const { seaWaveHeight, seaWaveDirection } = point.warnInfo.wave[0];
            msgs.push(`航线于${time}在位置${lngLat}经过大浪区域！` + `浪信息：${seaWaveHeight}m ${seaWaveDirection}`);
          }
          if (point.warnInfo?.wind?.length) {
            const { knots, direction } = point.warnInfo.wind[0];
            msgs.push(`航线于${time}在位置${lngLat}经过大风区域！` + `风信息：${knots}kts ${direction}`);
          }
          if (point.warnInfo?.abj?.length) {
            msgs.push(`航线于${time}在位置${lngLat}经过危险报文区域！` + point.warnInfo.abj.map(wxMsg => `报告内容：${wxMsg.description} ${wxMsg.weatherContent}`).join('; '));
          }
          const records = msgs.join('; ')
          const marker = getWarningMarker(() => taskStore.updateRegionWxMsgInfo(records));
          marker.setLngLat([lon, lat]).addTo(weatherStore.map as any);
          warningMarkers.value.push({
            id: warningId,
            lat, lon,
            marker: marker as any,
            records,
          });
        }
      });
    });
  } catch(err) {
    console.log(err);
  }
};

/** 清除风险提示 */
const clearTaskWarning = () => {
  warningMarkers.value.forEach(item => {
    item.marker.remove();
  });
  warningMarkers.value = [];
  taskStore.updateRouteLayer()
  taskStore.removeRouteWindWaveMarkers()
  taskStore.infoShow.regionWxMsg = false;
};

/**
 * 从外部关闭taskInfoShow
 */
const setTaskInfoShow = (visible: boolean) => {
  taskInfoShow.value = visible;
};

const toTaskInfo = (task: TaskItem) => {
  focusOnTask(task);
  const { id, taskStage, taskLtLongitude, taskLtLatitude, taskRbLongitude, taskRbLatitude, routeType, routes } = task;
  clickActiveTaskId.value = -1;
  if (task.taskStage !== TaskType.taskPrepare) {
    getTaskAttitude(id);
  }
  chosenTaskCustomRoute.value = [];
  if (task.taskStage === TaskType.warStart) {
    getTaskCustomRoute(id);
  }
  getTaskWarnings(id);
  chosenTask.value = task;
  show.value = false;
  taskInfoShow.value = true;
  taskStore.showTaskRoutePoint(id);
  // 设置currentTaskId
  taskStore.setCurrentTask(id)
  if (taskStage === TaskType.warStart) {
    updateTaskRegionSrc(weatherStore.map as any, [[taskLtLongitude!, taskLtLatitude!], [taskRbLongitude!, taskRbLatitude!]]);
  }
  if (routeType.some(type => routes?.[type]?.length)) {
    let startTime = Infinity;
    let endTime = 0;
    routeType.forEach(type => {
      if (routes?.[type]?.length) {
        const [newStart, newEnd] = getFirstAndLastTime(routes?.[type], startTime, endTime);
        startTime = newStart;
        endTime = newEnd;
      }
    });
    if (endTime > 0) {
      timeRangeStore.updateTimeRange(startTime, endTime);
    }
  }
};

const toggleTaskDisplay = (task: TaskItem) => {
  taskStore.toggleTaskVisible(task.id);
};

const toggleAllTask = () => {
  taskStore.toggleAllTasksVisible(false);
};

const focusOnTask = (task: TaskItem) => {
  taskStore.focusOnTask(task.id);
  mapFitTaskBounds(task);
};

const closeTaskInfo = () => {
  taskInfoShow.value = false;
  taskInfoRef.value?.toRouteList();
  timeRangeStore.refreshTimeRange();
  taskStore.showTaskRoutePoint();
  updateTaskRegionSrc(weatherStore.map as any);
  hideRegionRoute(weatherStore.map as any);
  taskStore.removeRoutePointMarker();
  clearTaskWarning();
  taskStore.setCurrentTask(null)
};

const handleReturn = () => {
  closeTaskInfo();
  show.value = true;
  taskStore.updateRouteLayer()
  taskStore.removeRoutePointMarker();
  taskStore.removeRouteWindWaveMarkers()
};

const toggleShow = () => {
  // 1. 取消高亮任何已选中的航线点
  clickActiveTaskId.value = -1;

  // 2. 计算新的可见状态：取反当前的 `show.value`
  //    `show` 是一个计算属性，和 <ElDialog v-model="show"> 绑定
  const visible = !show.value;

  // 3. 在地图上移除所有航线点的 Marker
  taskStore.removeRoutePointMarker();

  // 4. 如果“任务详情”面板（TaskInfo）当前打开，则调用 closeTaskInfo 做收尾
  if (taskInfoShow.value) {
    closeTaskInfo();
  }

  // 5. 如果切换后是显示任务列表（visible === true），确保任务详情面板隐藏
  if (visible) {
    taskInfoShow.value = false;
  }

  // 6. 最终将对话框的可见状态应用回去，触发打开或关闭
  show.value = visible;
};

const handleSaveRoute = async () => {
  // 1) 重新拉取任务列表，确保 routeType 的变更（如删除）立即反映到父组件
  await taskStore.getList();

  // 2) 用最新列表重找当前任务，保证传入 TaskInfo 的 props.task 是最新引用
  const id = chosenTask.value?.id;
  const task = id ? taskStore.list.find(item => item.id === id) : undefined;

  if (task) {
    // 3) 重新进入 TaskInfo（内部会重新计算时间范围、刷新地图、拉取告警等）
    toTaskInfo(task);
  } else {
    // 4) 任务可能被删除或不可用时，安全回退到任务列表
    closeTaskInfo();
    show.value = true;
  }
};

const handleRouteClick = async (e: MapMouseEvent & {
  features?: GeoJSONFeature[] | undefined;
}) => {
  const properties = e.features![0].properties as any;
  clickActiveTaskId.value = properties.id || -1;
  const idx = taskStore.list.findIndex(task => task.id === properties.id);
  if (idx > -1) {
    const location = (document.querySelector(`.task-list-container .list-row:nth-child(${idx})`) as HTMLDivElement)?.offsetTop || 0;
    scrollbarRef.value?.scrollTo({
      top: location,
      behavior: 'smooth',
    });
  }
};

const getActiveTaskAttitudeInfo = () => {
  return {
    id: chosenTask.value?.id,
    poses: chosenTaskAttitude.value,
    custom: chosenTaskCustomRoute.value,
  };
};

const handleExportProduct = () => {
  exportDialogRef.value?.showDialog();
};

watch(() => timeRangeStore.currentTime, () => {
  taskStore.updateAllShipMarker();
});

watch(() => weatherStore.map, (val) => {
  if (val) {
    if (!mapListenerAdded) {
      mapListenerAdded = true;
      val.on('click', [shipRouteLayerId], handleRouteClick);
    }
  }
});

defineExpose({
  toggleShow,
  getActiveTaskAttitudeInfo,
  setTaskInfoShow,
});
</script>

<template>
  <ElDialog
    :class="['custom-dialog', 'task-list-dialog']"
    v-model="show"
    title=""
    v-if="userStore.taskPhase !== 5"
    width="520"
    :modal="false"
    modal-class="pointer-none-dialog-modal"
    :close-on-click-modal="false"
    :align-center="false"
  >
    <div
      v-if="taskStore.loading"
      v-loading="taskStore.loading"
      class="table-loading"
      element-loading-background="transparent"
      :style="{height: '180px'}"
    >
    </div>
    <Empty v-else-if="taskStore.list.length === 0" height="180px"/>
    <template v-else>
      <div class="list-header">
        <div class="list-col-name">任务编号</div>
        <div class="list-col-loc">起终点</div>
        <div class="list-col-action">操作
          <ElButton
            type="primary"
            link
            @click.stop="() => toggleAllTask()"
          >
            <img :src="ClearSvgUrl" alt="clear" class="icon-clear" />
          </ElButton>
        </div>
      </div>
      <ElScrollbar ref="scrollbarRef" max-height="300px" class="task-list-container">
        <div v-for="item in taskStore.list" :key="item.id" :class="['list-row', {'list-row-active': clickActiveTaskId === item.id}]" @click="() => toTaskInfo(item)">
          <div class="list-col-name">{{ item.name }}</div>
          <div class="list-col-loc">
            <div>{{ item.points[0]?.name || toLonLatString(item.points[0]?.longitude, item.points[0]?.latitude) }}</div>
            <div>{{ item.points[item.points.length - 1]?.name || toLonLatString(item.points[item.points.length - 1]?.longitude, item.points[item.points.length - 1]?.latitude) }}</div>
          </div>
          <div v-if="judgeItemStatus(item)" class="list-col-action">
            <ElButton type="primary" link @click.stop="() => focusOnTask(item)" :icon="Aim"></ElButton>
            <ElButton type="primary" link @click.stop="() => toggleTaskDisplay(item)" :icon="taskStore.hideTasks.includes(item.id) ? Hide : View"></ElButton>
            <ElButton v-if="false" type="primary" link @click.stop="() => emits('edit', item)" :icon="Edit"></ElButton>
          </div>
          <div v-else class="list-col-action">
            <ElButton type="primary" link disabled>规划中</ElButton>
          </div>
        </div>
      </ElScrollbar>
    </template>
  </ElDialog>
  <TaskInfo
    ref="taskInfoRef"
    v-model:visible="taskInfoShow"
    :task="chosenTask"
    :poses="chosenTaskAttitude"
    :poses-loading="attitudeLoading"
    :custom-loading="customRouteLoading"
    :custom-route-pose="chosenTaskCustomRoute"
    @return="handleReturn"
    @save-route="handleSaveRoute"
    @refresh-custom-route="getTaskCustomRoute"
    @export="handleExportProduct"
  />
  <ExportDialog ref="exportDialogRef" :task="chosenTask" />
</template>

<style lang="less" scoped>
.list-header,
.list-row {
  display: flex;
  align-items: center;
  font-weight: 400;
  font-size: 14px;
  color: #FFFFFF;
  line-height: 20px;
}
.list-header {
  padding: 0 8px;
  margin-bottom: 8px;
}
.list-row {
  padding: 5px 8px;
  background: linear-gradient( 53deg, rgba(129,201,255,0.24) 0%, rgba(120,196,255,0.08) 100%);
  border-radius: 4px;
  cursor: pointer;
  &:not(:first-child) {
    margin-top: 8px;
  }
  &.list-row-active,
  &:hover {
    background: linear-gradient( 53deg, rgba(129,201,255,0.34) 0%, rgba(120,196,255,0.18) 100%);
  }
}
.list-col-name {
  width: 190px;
  flex-shrink: 0;
  margin-right: 4px;
}
.list-col-loc {
  width: 190px;
  flex-shrink: 0;
  margin-right: 4px;
}
.list-col-action {
  button {
    border: none;
    padding: 8px 8px 8px 0;
    margin-left: 0;
    font-size: 18px;
  }
}
</style>

<style scoped>
.icon-clear {
  width: 16px;
  height: 16px;
  vertical-align: middle;
}
</style>

<style lang="less">
.custom-dialog.task-list-dialog.el-dialog {
  margin-left: 20px;
  border: none;
  opacity: 0.91;
  border-radius: 4px;
  box-shadow: 0px 2px 8px 0px rgba(0,0,0,0.07);
  --el-dialog-bg-color: linear-gradient( 180deg, rgba(0,54,97,0.89) 0%, rgba(25,36,57,0.92) 100%);
  --el-dialog-margin-top: 95px;
  .el-dialog__body {
    padding: 0 0;
  }
  .dialog-footer {
    padding: 6px 76px 0 60px;
  }
  .el-dialog__header {
    display: none;
  }
}
</style>
